// Copyright (c) 2005  INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of cgal-python; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free SoFTware Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with cgal-python.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the soFTware.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $Id: Py_global_functions_2.cpp 176 2007-11-07 15:44:39Z spion $
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal-python/trunk/cgal-python/bindings/Kernel/Py_global_functions_2.cpp $
//
// Author(s)     : Naceur Meskini
//=========================================================================

#include <CGAL/basic.h>
#include <include/Kernels.h>
#include <CGAL/Kernel/global_functions_2.h>

#include <boost/python.hpp>
#include <boost/cstdint.hpp>

// template<class kernel>
// boost::python::object intersection(boost::python::object obj1,boost::python::object obj2)
// {
// 	 CGAL::Line_2<kernel> l1 = boost::python::extract< CGAL::Line_2<kernel> >(obj1);
// 	 CGAL::Line_2<kernel> l2 = boost::python::extract< CGAL::Line_2<kernel> >(obj2);
// 	 CGAL::Object o = CGAL::intersection(l1,l2);
//  	if ( typeid(CGAL::Point_2<kernel>) == o.type() ){
// 		CGAL::Point_2<kernel> l;
// 		CGAL::assign(l,o);
// 		return boost::python::object(l);
// 	}
// 	return boost::python::object( CGAL::Line_2<kernel>() );
// }



template <class kernel > 
void Py_global_functions_2()
{
	typedef typename kernel::Point_2  		Point_2;
	typedef typename kernel::Line_2  		Line_2;
	typedef typename kernel::Segment_2  	Segment_2;
	typedef typename kernel::Triangle_2  	Triangle_2;

	typedef typename kernel::FT FT;
	using namespace boost::python;

// 	def("intersection",&intersection<kernel>);
    //def("squared_radius", (FT (*)(const Point_2&, const Point_2&))&CGAL::squared_radius);
    //def("squared_radius", (FT (*)(const Point_2&, const Point_2&, const Point_2&))&CGAL::squared_radius);
    def("side_of_oriented_circle",  (CGAL::Oriented_side (*)(const Point_2&, const Point_2&, const Point_2&, const Point_2&))&CGAL::side_of_oriented_circle);

    def("x_equal", (bool (*)(const Point_2&, const Point_2&))&CGAL::x_equal);
    def("y_equal", (bool (*)(const Point_2&, const Point_2&))&CGAL::y_equal);

    def("side_of_bounded_circle", (CGAL::Bounded_side (*)(const Point_2&, const Point_2&, const Point_2&))&CGAL::side_of_bounded_circle);
    def("side_of_bounded_circle", (CGAL::Bounded_side (*)(const Point_2&, const Point_2&, const Point_2&, const Point_2&))&CGAL::side_of_bounded_circle);

    def("compare_y_at_x", (CGAL::Comparison_result (*)(const CGAL::Line_2<kernel >&, const CGAL::Line_2<kernel >&, const CGAL::Line_2<kernel >&, const CGAL::Line_2<kernel >&))&CGAL::compare_y_at_x);
    def("compare_y_at_x", (CGAL::Comparison_result (*)(const Line_2&, const Line_2&, const Line_2&, const Line_2&))&CGAL::compare_y_at_x);
    def("compare_y_at_x", (CGAL::Comparison_result (*)(const Point_2&, const Line_2&, const Line_2&))&CGAL::compare_y_at_x);
    def("compare_y_at_x", (CGAL::Comparison_result (*)(const Line_2&, const Line_2&, const Line_2&))&CGAL::compare_y_at_x);
    def("compare_y_at_x", (CGAL::Comparison_result (*)(const Point_2&, const Segment_2&, const Segment_2&))&CGAL::compare_y_at_x);
    def("compare_y_at_x", (CGAL::Comparison_result (*)(const Point_2&, const Line_2&))&CGAL::compare_y_at_x);
    def("compare_y_at_x", (CGAL::Comparison_result (*)(const Point_2&, const Segment_2&))&CGAL::compare_y_at_x);

    def("has_larger_distance_to_point", (bool (*)(const Point_2&, const Point_2&,const Point_2&))&CGAL::has_larger_distance_to_point);

    def("has_larger_signed_distance_to_line", (bool (*)(const Line_2&, const Point_2&, const Point_2&))&CGAL::has_larger_signed_distance_to_line);
    def("has_larger_signed_distance_to_line", (bool (*)(const Point_2&, const Point_2&, const Point_2&, const Point_2&))&CGAL::has_larger_signed_distance_to_line);

    def("has_smaller_distance_to_point", (bool (*)(const Point_2&, const Point_2&,const Point_2&))&CGAL::has_smaller_distance_to_point);

    def("compare_y_at_x", (CGAL::Comparison_result (*)(const Line_2&, const Line_2&, const Line_2&, const Line_2&))&CGAL::compare_y_at_x);
    def("compare_y_at_x", (CGAL::Comparison_result (*)(const Point_2&, const Line_2&, const Line_2&))&CGAL::compare_y_at_x);
    def("compare_y_at_x", (CGAL::Comparison_result (*)(const Line_2&, const Line_2&, const Line_2&))&CGAL::compare_y_at_x);
    def("compare_y_at_x", (CGAL::Comparison_result (*)(const Point_2&, const Segment_2&, const Segment_2&))&CGAL::compare_y_at_x);
    def("compare_y_at_x", (CGAL::Comparison_result (*)(const Point_2&, const Line_2&))&CGAL::compare_y_at_x);
    def("compare_y_at_x", (CGAL::Comparison_result (*)(const Point_2&, const Segment_2&))&CGAL::compare_y_at_x);

    def("compare_x", (CGAL::Comparison_result (*)(const Point_2&, const Point_2&))&CGAL::compare_x);
    def("compare_x", (CGAL::Comparison_result (*)(const Point_2&, const Line_2&, const Line_2&))&CGAL::compare_x);
    def("compare_x", (CGAL::Comparison_result (*)(const Line_2&, const Line_2&, const Line_2&))&CGAL::compare_x);
    def("compare_x", (CGAL::Comparison_result (*)(const Line_2&, const Line_2&, const Line_2&, const Line_2&))&CGAL::compare_x);

    def("compare_signed_distance_to_line", (CGAL::Comparison_result (*)(const Point_2&, const Point_2&, const Point_2&, const Point_2&))&CGAL::compare_signed_distance_to_line);
    def("compare_signed_distance_to_line", (CGAL::Comparison_result (*)(const Line_2&, const Point_2&, const Point_2&))&CGAL::compare_signed_distance_to_line);
    def("compare_slopes", (CGAL::Comparison_result (*)(const Line_2&, const Line_2&))&CGAL::compare_slopes);
    def("compare_slopes", (CGAL::Comparison_result (*)(const Segment_2&, const Segment_2&))&CGAL::compare_slopes);
    def("compare_slopes", (CGAL::Comparison_result (*)(const Line_2&, const Line_2&))&CGAL::compare_slopes);
    def("compare_slopes", (CGAL::Comparison_result (*)(const Segment_2&, const Segment_2&))&CGAL::compare_slopes);
    def("compare_angle_with_x_axis", (CGAL::Comparison_result (*)(const CGAL::Direction_2<kernel >&, const CGAL::Direction_2<kernel >&))&CGAL::compare_angle_with_x_axis);
    def("compare_distance_to_point", (CGAL::Comparison_result (*)(const Point_2&, const Point_2&, const Point_2& ))&CGAL::compare_distance_to_point);
    def("are_strictly_ordered_along_line", (bool (*)(const Point_2&, const Point_2&, const Point_2&))&CGAL::are_strictly_ordered_along_line);

    //def("area", (FT (*)(const Point_2&, const Point_2&, const Point_2&))&CGAL::area);

    def("angle", (CGAL::Angle (*)(const Point_2&, const Point_2&, const Point_2&))&CGAL::angle);
    def("are_ordered_along_line", (bool (*)(const Point_2&, const Point_2&, const Point_2&))&CGAL::are_ordered_along_line);
    def("has_smaller_signed_distance_to_line", (bool (*)(const Point_2&, const Point_2&, const Point_2&, const Point_2&))&CGAL::has_smaller_signed_distance_to_line);
    def("has_smaller_signed_distance_to_line", (bool (*)(const Line_2&, const Point_2&, const Point_2&))&CGAL::has_smaller_signed_distance_to_line);
//    def("min_vertex", (Point_2(*)(const CGAL::Iso_rectangle_2<kernel>&))&CGAL::min_vertex);
    def("has_smaller_signed_distance_to_line", (bool (*)(const Point_2&, const Point_2&, const Point_2&, const Point_2&))&CGAL::has_smaller_signed_distance_to_line);
    def("has_smaller_signed_distance_to_line", (bool (*)(const Line_2&, const Point_2&, const Point_2&))&CGAL::has_smaller_signed_distance_to_line);
//    def("midpoint", (Point_2(*)(const Point_2&, const Point_2&))&CGAL::midpoint);
//    def("max_vertex", (Point_2(*)(const CGAL::Iso_rectangle_2<kernel>&))&CGAL::max_vertex);
    def("orientation", (CGAL::Orientation (*)(const CGAL::Vector_2<kernel >&, const CGAL::Vector_2<kernel >&))&CGAL::orientation);
    def("orientation", (CGAL::Orientation (*)(const Point_2&, const Point_2&, const Point_2&))&CGAL::orientation);
    def("right_turn", (bool (*)(const Point_2&, const Point_2&, const Point_2&))&CGAL::right_turn);
    def("orientation", (CGAL::Orientation (*)(const CGAL::Vector_2<kernel >&, const CGAL::Vector_2<kernel >&))&CGAL::orientation);
    def("orientation", (CGAL::Orientation (*)(const Point_2&, const Point_2&, const Point_2&))&CGAL::orientation);
    def("lexicographically_yx_larger", (bool (*)(const Point_2&, const Point_2&))&CGAL::lexicographically_yx_larger);
    def("lexicographically_yx_larger_or_equal", (bool (*)(const Point_2&, const Point_2&))&CGAL::lexicographically_yx_larger_or_equal);
    def("less_y", (bool (*)(const Point_2&, const Point_2&))&CGAL::less_y);
    def("less_x", (bool (*)(const Point_2&, const Point_2&))&CGAL::less_x);
    def("lexicographically_xy_larger_or_equal", (bool (*)(const Point_2&, const Point_2&))&CGAL::lexicographically_xy_larger_or_equal);
    def("lexicographically_xy_larger", (bool (*)(const Point_2&, const Point_2&))&CGAL::lexicographically_xy_larger);
    def("lexicographically_xy_smaller_or_equal", (bool (*)(const Point_2&, const Point_2&))&CGAL::lexicographically_xy_smaller_or_equal);
    def("lexicographically_xy_smaller", (bool (*)(const Point_2&, const Point_2&))&CGAL::lexicographically_xy_smaller);
    def("left_turn", (bool (*)(const Point_2&, const Point_2&, const Point_2&))&CGAL::left_turn);

    def("compare_x_at_y", (CGAL::Comparison_result (*)(const Point_2&, const Line_2&, const Line_2&))&CGAL::compare_x_at_y);
    def("compare_x_at_y", (CGAL::Comparison_result (*)(const Point_2&, const Line_2&))&CGAL::compare_x_at_y);
    def("compare_x_at_y", (CGAL::Comparison_result (*)(const Line_2&, const Line_2&, const Line_2&, const Line_2&))&CGAL::compare_x_at_y);
    def("compare_x_at_y", (CGAL::Comparison_result (*)(const Line_2&, const Line_2&, const Line_2&))&CGAL::compare_x_at_y);


    def("compare_y", (CGAL::Comparison_result (*)(const Line_2&, const Line_2&, const Line_2&))&CGAL::compare_y);
    def("compare_y", (CGAL::Comparison_result (*)(const Line_2&, const Line_2&, const Line_2&, const Line_2&))&CGAL::compare_y);
    def("compare_y", (CGAL::Comparison_result (*)(const Point_2&, const Line_2&, const Line_2&))&CGAL::compare_y);
    def("compare_xy", (CGAL::Comparison_result (*)(const Point_2&, const Point_2& ))&CGAL::compare_xy);


    def("compare_x_at_y", (CGAL::Comparison_result (*)(const Line_2&, const Line_2&, const Line_2&))&CGAL::compare_x_at_y);
    def("compare_y_at_x", (CGAL::Comparison_result (*)(const Line_2&, const Line_2&, const Line_2&, const Line_2&))&CGAL::compare_y_at_x);
    def("compare_y_at_x", (CGAL::Comparison_result (*)(const Point_2&, const Line_2&, const Line_2&))&CGAL::compare_y_at_x);
    def("compare_y_at_x", (CGAL::Comparison_result (*)(const Line_2&, const Line_2&, const Line_2&))&CGAL::compare_y_at_x);
    def("compare_y_at_x", (CGAL::Comparison_result (*)(const Point_2&, const Segment_2&, const Segment_2&))&CGAL::compare_y_at_x);
    def("compare_y_at_x", (CGAL::Comparison_result (*)(const Point_2&, const Line_2&))&CGAL::compare_y_at_x);
    def("compare_y_at_x", (CGAL::Comparison_result (*)(const Point_2&, const Segment_2&))&CGAL::compare_y_at_x);
    
    def("compare_y", (CGAL::Comparison_result (*)(const Line_2&, const Line_2&, const Line_2&))&CGAL::compare_y);
    def("compare_y", (CGAL::Comparison_result (*)(const Line_2&, const Line_2&, const Line_2&, const Line_2&))&CGAL::compare_y);
    def("compare_y", (CGAL::Comparison_result (*)(const Point_2&, const Line_2&, const Line_2&))&CGAL::compare_y);   
    def("compare_y", (CGAL::Comparison_result (*)(const Point_2&, const Point_2&))&CGAL::compare_y);

    //to be commented if you expecte to use the exact Kernel
//	def("bisector", (Line_2 (*)(const Line_2&, const Line_2&))&CGAL::bisector);
//    def("bisector", (Line_2 (*)(const Point_2&, const Point_2&))&CGAL::bisector);
	

    def("collinear", (bool (*)(const Point_2&, const Point_2& , const Point_2& ))&CGAL::collinear);
    def("collinear_are_strictly_ordered_along_line", (bool (*)(const Point_2&, const Point_2& , const Point_2& ))&CGAL::collinear_are_strictly_ordered_along_line);
    def("collinear_are_ordered_along_line", (bool (*)(const Point_2&, const Point_2& , const Point_2& ))&CGAL::collinear_are_ordered_along_line);
    def("centroid", (Point_2 (*)(const Triangle_2&))&CGAL::centroid);//CGAL::centroid(Triangle_2());
//    def("centroid", (Point_2 (*)(const Point_2&, const Point_2&, const Point_2&))&CGAL::centroid);
//    def("centroid", (Point_2 (*)(const Point_2&, const Point_2&, const Point_2&, const Point_2&))&CGAL::centroid);
    //def("circumcenter", (Point_2 (*)(const Triangle_2&))&CGAL::circumcenter);
    //def("circumcenter", (Point_2 (*)(const Point_2&, const Point_2&, const Point_2&))&CGAL::circumcenter);
}

void export_global_functions_2()
{
	Py_global_functions_2<K>();
}
